#pragma once
#ifndef checkvec
#define checkvec
#include <vector>
#include <cassert>
#include <functional>
#include <iterator>
using namespace std;

template<class T>
class checkvector : public vector<T>
{
public:
	checkvector()
	{}

	checkvector(size_type n, const T& value = T()) : vector<T>(n, value)
	{}

	checkvector(iterator i, iterator j) : vector<T>(i, j)
	{}

	reference operator[](difference_type index)
	{
		if(index<0||index>=size())
			throw string("index illegal");
		return vector<T>::operator [](index);
	}

	const_reference operator[](difference_type index) const
	{
		if(index<0||index>=size())
			throw string("index illegal");
		return vector<T>::operator [](index);
	}
};
#endif

#ifndef _2dmatrix
#define _2dmatrix
template<class T>
class matrix : public checkvector<checkvector<T> >
{
//size and column
protected:
	size_type rows;
	size_type columns;

//memeber function
public:
	matrix(size_type x=0, size_type y=0)
		: checkvector<checkvector<T> >(x, checkvector<T>(y)), rows(x), columns(y)
	{}

	size_type getrows() const
	{return rows;}

	size_type getcolumns() const
	{return columns;}

	//initialize the matrix
	void initialize(const T& value)
	{
		for(size_type i=0; i<rows; i++)
			for(size_type j=0; j<columns; j++)
				operator[](i)[j] = value;
	}
};

//initialize a matrix
template<class T>
ostream& operator << (ostream& s, const matrix <T>& m)
{
	typedef matrix<T>::size_type size_type;
	for(size_type i=0; i<m.getrows(); i++)
	{
		for(size_type j=0; j<m.getcolumns(); j++)
		{
			s << m[i][j] <<"\t";
		}
		s << endl;
	}
	return s;
};

template<class T> struct initializevalue : public std::unary_function<T&, void>
{
	initializevalue(T initialvalue) : iv(initialvalue) {}
	void operator() (T& x) {x = iv;}
	T iv;
};

template<class T> struct print : public unary_function<T, void>
{
  print(ostream& out) : os(out) {}
  void operator() (T x) { os << x << "\r\n";}
  ostream& os;
};

template<typename T> struct multiplybynumber : public unary_function<T, T>
{
	multiplybynumber(T multiplynumber) : number(multiplynumber) {}
	T operator() (T& x) {return x * number;}
private:
	T number;
};

#endif
